#ifndef PAGING_H
#define PAGING_H

#include <types.h>

#define PAGE_SIZE 4096
#define PAGE_TABLE_SIZE 1024

#define IS_PAGE_ALIGNED(x) (((x) & 0xFFF) == 0)
#define ENSURE_PAGE_ALIGNED(x) do { if((x) & 0xFFF) { (x) &= 0xFFFFF000; (x) += PAGE_SIZE; } } while(0)
#define WRITEABLE 0x1
#define KERNEL    0x2

struct page
{
    uint32 present   : 1;
    uint32 rw        : 1;
    uint32 user      : 1;
    uint32 accessed  : 1;
    uint32 dirty     : 1;
    uint32 unused    : 7;
    uint32 frame     : 20;
};



struct page_table
{
    struct page pages[PAGE_TABLE_SIZE];
};

struct page_directory
{
    // array of pointers to our page tables
    struct page_table *tables[PAGE_TABLE_SIZE];
    
    // physical address of our tables to load on the CR3 register
    uint32 tables_addresses[PAGE_TABLE_SIZE];

    // physical address of tables_addresses
    uint32 physical_address;
};

void paging_init(uint32 mem_end);

void set_page_directory(struct page_directory *new);
struct page *get_page(struct page_directory *dir, uint32 address);
struct page *new_page(struct page_directory *dir, uint32 address, uint8 flags);
void alloc_frame(struct page *p, uint8 flags);
void free_frame(struct page *p);

#endif


